package com.sso.manager;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tools.util.StrUtils;
import com.sso.common.ConstantDate;
import com.sso.common.enums.SysResourceEnum;
import com.sso.dao.SysResourceMapper;
import com.sso.entity.Page;
import com.sso.entity.SysResource;
import com.sso.entity.vo.SysResourceVo;
import com.sso.exception.SelectException;
import com.sso.sys.annotation.ResourceInfo;

@Service("sysResourceManager")
public class SysResourceManager {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SysResourceMapper resDao;

    @Transactional(rollbackFor = Exception.class)
    public void saveResource(SysResource res) throws Exception {
        List<SysResource> list = new ArrayList<SysResource>();
        list.add(res);
        this.saveResource(list);
    }
    @Transactional(rollbackFor = Exception.class)
    public int saveResource(List<SysResource> list) throws Exception {
        int i=0;
        for (SysResource res : list) {
            if (StrUtils.isEmpty(res.getId())) {
                res.setId(ConstantDate.getUUID());
                res.setStatus(StrUtils.doNull(res.getStatus(),SysResourceEnum.status.START.key));
                //接口类型的资源没有权限，其它类型资源默认为login
                if(SysResourceEnum.type.WEB_SERVICE.key.equals(res.getType())){
                    res.setAuthType(SysResourceEnum.AuthType.ANON.key);
                }else {
                    res.setAuthType(StrUtils.doNull(res.getAuthType(), SysResourceEnum.AuthType.LOGIN.key));
                }
                i+=resDao.insert(res);
            } else {
                i+=resDao.update(res);
            }
        }
        return i;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public List<SysResourceVo> selectVoByProperty(Map<String, Object> filterMap){
        return resDao.selectVoByProperty(filterMap);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public List<SysResource> selectByProperty(Map<String, Object> filterMap){
        return resDao.selectByProperty(filterMap);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public SysResource selectByid(String id){
        Map<String, Object> filterMap = new HashMap<String, Object>();
        filterMap.put("id", id);
        return this.selectByUnique(filterMap);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public SysResourceVo selectVoById(String id){
        Map<String,Object> param = new HashMap<String, Object>();
        param.put("id",id);
        return this.selectByUnique(param);
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertForBatch(List<SysResource> list) throws Exception {
        resDao.insertForBatch(list);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveAuthType(String type, SysResource res) throws Exception {
        //默认
        if ("def".equals(type)) {//默认
            res.setAuthType(SysResourceEnum.AuthType.DEFAULT.key);
        } else if ("anon".equals(type)) {        //不限制
            res.setAuthType(SysResourceEnum.AuthType.ANON.key);
        } else if ("login".equals(type)) {
            res.setAuthType(SysResourceEnum.AuthType.LOGIN.key);
        }else{
            return;
        }
        resDao.update(res);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public Page<SysResourceVo> selectByPage(Map<String, Object> filterMap){
        String pageNo = StrUtils.doNull((String) filterMap.get("pageNo"), "1");
        String pageSize = StrUtils.doNull((String) filterMap.get("pageSize"), "10");
        Page<SysResourceVo> page = new Page<SysResourceVo>(pageNo, pageSize);
        filterMap.put("first", page.getFirst());
        filterMap.put("last", page.getLast());
        List<SysResourceVo> list = resDao.selectByPage(filterMap);
        long totalCount = resDao.countByProperty(filterMap);
        page.setTotalCount(totalCount);
        page.setData(list);
        return page;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public SysResource selectByURL(String url){
        SysResource resource = new SysResource();
        if(StrUtils.isEmpty(url)){
            return resource;
        }
        Map<String,Object> filterMap = new HashMap<String, Object>();
        filterMap.put("url",url);
        resource = this.selectByUnique(filterMap);
        return resource;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public SysResourceVo selectByUnique(Map<String,Object> param){
        List<SysResourceVo> voList = this.selectVoByProperty(param);
        if(voList.size()==0){
            return new SysResourceVo();
        }
        if(voList.size()>1){
            logger.info("SysResourceManager-->selectByUnique查询错误，错误原因：集合过大..........");
            return new SysResourceVo();
        }
        return voList.get(0);
    }
    /**
     * 封装所有action资源
     *
     * @param packageName
     * @param dirs
     * @param resList
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void getAllRefreshResource(String packageName, File[] dirs, List<SysResource> resList) {
        for (File f : dirs) {
            //判断是否是一个目录
            if (f.isDirectory()) {
                //采用递归算法获取当前目录下所有文件的资源集合
                this.getAllRefreshResource(packageName + "." + f.getName(), f.listFiles(), resList);
            } else {
                String className = f.getName().substring(0, f.getName().length() - 6);
                // 拼接上包名，变成全限定名
                String actionName = packageName + "." + className;
                try {
                    Class<?> c = Class.forName(actionName);
                    //判断是否包含RequestMapping注解
                    if (!c.isAnnotationPresent(RequestMapping.class)) {
                        continue;
                    }
                    //获取当前action的注解
                    RequestMapping classAnnotation = c.getAnnotation(RequestMapping.class);
                    // 获取action下所有的方法实例
                    Method[] methodArray = c.getMethods();
                    for (Method method : methodArray) {
                        // 判断该方法是否包含MyAnnotation注解
                        if (!method.isAnnotationPresent(RequestMapping.class)) {
                            continue;
                        }
                        // 获取该方法的MyAnnotation注解实例
                        RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                        Deprecated deprecatedAnnotaion = method.getAnnotation(Deprecated.class);
                        if (classAnnotation != null) {
                            //查询是否已经存在该资源
                            Map<String, Object> filterMap = new HashMap<String, Object>();
                            filterMap.put("action", c.getSimpleName());
                            filterMap.put("method", method.getName());
                            List<SysResource> list = this.selectByProperty(filterMap);
                            SysResource res = new SysResource();
                            if (list.size() == 1) {
                                res = list.get(0);
                            }
                            String classAnno = classAnnotation.value()[0];
                            String methodAnno = methodAnnotation.value()[0];
                            if (StrUtils.isNotEmpty(classAnnotation.value()[0]) && classAnnotation.value()[0].indexOf("/") == -1) {
                                classAnno = "/" + classAnnotation.value()[0];
                            }
                            if (methodAnnotation.value()[0].indexOf("/") == -1) {
                                methodAnno = "/" + methodAnnotation.value()[0];
                            }
                            //方法已被弃用
                            if(deprecatedAnnotaion!=null){
                                res.setStatus(SysResourceEnum.status.DEL.key);
                            }
                            //该类为接口类
                            if(classAnno.startsWith("/ws/")){
                                res.setType(SysResourceEnum.type.WEB_SERVICE.key);
                            }else{
                                res.setType(SysResourceEnum.type.ACTION.key);
                            }
                            res.setAction(c.getSimpleName());
                            res.setMethod(method.getName());
                            res.setUrl(classAnno + methodAnno);
                            resList.add(res);
                        }
                    }
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    continue;
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }
            }
        }
    }
}
